// Author: Domien Nowicki

#include "VersusGame.h"
using namespace std;

VersusGame::VersusGame(const Map& newMap, const Properties& properties, Highscore& newHighscore): Game(properties), map(&newMap), humanMap(0), humanPlayer(0), computerMap(0), computerPlayer(0), clock(0), highscore(&newHighscore), turn(HUMAN), hintPenalty(0)
{
	// Hints is allowed for this game, coloring the map is not
	SetAllowHints(true);
	SetAllowColorMap(false);
}


VersusGame::~VersusGame()
{
	Clear();
}

void VersusGame::Clear()
{
	// Clear clock
	if (clock)
	{
		delete clock;

		clock = 0;
	}

	// Clear human player and map
	if (humanPlayer)
	{
		delete humanPlayer;

		humanPlayer = 0;
	}
	
	if (humanMap)
	{
		delete humanMap;

		humanMap = 0;
	}

	// Clear computer player and map
	if (computerPlayer)
	{
		delete computerPlayer;

		computerPlayer = 0;
	}

	if (computerMap)
	{
		delete computerMap;

		computerMap = 0;
	}
}

int VersusGame::GetTime() const
{
	// Get the amount of time this clock has been running since it was created
	return clock->GetLifeTime();
}

const Highscore& VersusGame::GetHighscore()
{
	return *highscore;
}

void VersusGame::Start()
{
	// Clear game states
	Clear();

	Output("Starting a new versus game.");

	// Start general game
	Game::Start();

	// Create a new descending clock
	clock = NewClock(Clock::DESCENDING);

	// Create players and their maps
	humanMap = NewMap(*map);
	humanPlayer = NewHumanPlayer(humanMap);

	computerMap = NewMap(*map);
	computerPlayer = new Player(this, computerMap, GetProperties());

	// Do the first turn
	DoTurn();
}


void VersusGame::Stop()
{
	// Stop game and clock
	Game::Stop();

	clock->Stop();
}


void VersusGame::Hint()
{
	// Can only give a hint if the game is active
	if (IsActive())
	{
		Output("Asking for a hint, switching turns");

		SetHintPenalty(HINTPENALTY);

		Move move;

		// Get a hint move
		humanPlayer->GetHintMove(&move);

		// Do the move
		DoMove(humanPlayer, move);
	}
}


void VersusGame::EndGame(const Player *player)
{
	// The game has been ended
	Game::EndGame(player);

	// Stop the clock
	clock->Stop();

	Score score;

	// Fill in the score data
	score.SetStepCount(player->GetStepCount());
	score.SetTime(GetTime());
	score.SetColorCount(player->GetMap()->GetUniqueColorCount());

	// Can only add in the score if the winning player is a human (and if it will get inserted)
	if (player->IsHuman() && highscore->TestScoreInsert(score))
	{
		std::string name;

		// If user wanted to fill in his name
		if (GetName(&name))
		{
			score.SetName( name );

			// Insert the score and save it to a file on disk
			highscore->InsertScore(score);
			highscore->Save();

			// Show the highscores
			ShowHighscore(GetHighscore());
		}
	}
}


void VersusGame::Timeout()
{
	// Player's turn timed out
	Output("Player turn timed out.");

	// Switch turns
	SwitchTurn();
}

void VersusGame::SetHintPenalty(int penalty)
{
	hintPenalty = penalty;
}

void VersusGame::SwitchTurn()
{
	// If player asked for a hint, the computer may set 1 move extra
	if (hintPenalty > 0)
	{
		turn = COMPUTER;

		hintPenalty--;
	}
	else
	{
		// Else toggle turns between human and computer
		if (HUMAN == turn)
		{
			turn = COMPUTER;
		}
		else
		{
			turn = HUMAN;
		}
	}

	// Do the turn
	DoTurn();
}

void VersusGame::DoTurn()
{
	// Stop clock
	clock->Stop();

	if (turn == COMPUTER)
	{
		Move m;

		// Get and do the computer's move
		computerPlayer->GetMove(&m);

		DoMove(computerPlayer, m);
	}
	else
	{
		// Reset clock
		clock->Start(MAXTURNTIME);

		// Wait for human player to respond
	}
}




